home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / MPW_TOOL / TOOLS / TOOLS_WI / ICON_8 / ICONT_FO / LSYM.C < prev    next >
Text File  |  1990-03-02  |  10KB  |  423 lines

  1. /*
  2.  * lsym.c -- functions for symbol table manipulation.
  3.  */
  4.  
  5. #include "::h:config.h"
  6. #include "tproto.h"
  7. #include "globals.h"
  8. #include "link.h"
  9. #include "general.h"
  10.  
  11. /*
  12.  * Prototypes.
  13.  */
  14.  
  15. hidden struct     fentry *alcfhead
  16.    Params((struct fentry *blink,char *name, int fid, struct rentry *rlist));
  17. hidden struct     rentry *alcfrec    
  18.    Params((struct rentry *link,int rnum, int fnum));
  19. hidden struct     tgentry *alcglob
  20.    Params((struct tgentry *blink, char *name, int flag,int nargs));
  21. hidden struct     gentry *alcglobal
  22.    Params((struct gentry *blink,char *name, int flag,int nargs,int procid));
  23. hidden struct     ientry *alcident    Params((char *nam,int len));
  24.  
  25. int dynoff;            /* stack offset counter for locals */
  26. int argoff;            /* stack offset counter for arguments */
  27. int static1;            /* first static in procedure */
  28. int lstatics = 0;        /* static variable counter */
  29.  
  30. int nlocal;            /* number of locals in local table */
  31. int nconst;            /* number of constants in constant table */
  32. int nfields = 0;        /* number of fields in field table */
  33.  
  34. /*
  35.  * instid - copy the string s to the start of the string free space
  36.  *  and call putident with the length of the string.
  37.  */
  38. char *instid(s)
  39. char *s;
  40.    {
  41.    register int l;
  42.    register char *p1, *p2;
  43.  
  44.    p1 = lsfree;
  45.    p2 = s;
  46.    l = 0;
  47.    do {
  48.       if (p1 > lsend)
  49.          quit("out of string space");
  50.       l++;
  51.       } while (*p1++ = *p2++);
  52.    return putident(l);
  53.    }
  54.  
  55. /*
  56.  * putident - install the identifier named by the string starting at lsfree
  57.  *  and extending for len bytes.  The installation entails making an
  58.  *  entry in the identifier hash table and then making an identifier
  59.  *  table entry for it with alcident.  A side effect of installation
  60.  *  is the incrementing of lsfree by the length of the string, thus
  61.  *  "saving" it.
  62.  *
  63.  * Nothing is changed if the identifier has already been installed.
  64.  */
  65. char *putident(len)
  66. int len;
  67.    {
  68.    register int hash;
  69.    register char *s;
  70.    register struct ientry *ip;
  71.    int l;
  72.  
  73.    /*
  74.     * Compute hash value by adding bytes and masking result with imask.
  75.     *  (Recall that imask is ihsize-1.)
  76.     */
  77.    s = lsfree;
  78.    hash = 0;
  79.    l = len;
  80.    while (l--)
  81.       hash += *s++;
  82.    l = len;
  83.    s = lsfree;
  84.    hash &= imask;
  85.    /*
  86.     * If the identifier hasn't been installed, install it.
  87.     */
  88.    if ((ip = lihash[hash]) != NULL) {     /* collision */
  89.       for (;;) { /* work down i_blink chain until id is found or the
  90.                      end of the chain is reached */
  91.          if (l == ip->i_length && lexeql(l, s, ip->i_name))
  92.             return (ip->i_name); /* id is already installed, return it */
  93.          if (ip->i_blink == NULL) { /* end of chain */
  94.             ip->i_blink = alcident(s, l);
  95.             lsfree += l;
  96.             return s;
  97.             }
  98.          ip = ip->i_blink;
  99.          }
  100.       }
  101.    /*
  102.     * Hashed to an empty slot.
  103.     */
  104.    lihash[hash] = alcident(s, l);
  105.    lsfree += l;
  106.    return s;
  107.    }
  108.  
  109. /*
  110.  * lexeql - compare two strings of given length.  Returns non-zero if
  111.  *  equal, zero if not equal.
  112.  */
  113. int lexeql(l, s1, s2)
  114. register int l;
  115. register char *s1, *s2;
  116.    {
  117.    while (l--)
  118.       if (*s1++ != *s2++)
  119.          return 0;
  120.    return 1;
  121.    }
  122.  
  123. /*
  124.  * alcident - get the next free identifier table entry, and fill it in with
  125.  *  the specified values.
  126.  */
  127. static struct ientry *alcident(nam, len)
  128. char *nam;
  129. int len;
  130.    {
  131.    register struct ientry *ip;
  132.  
  133.    if (lifree >= &litable[isize])
  134.       quit("out of identifier table space");
  135.    ip = lifree++;
  136.    ip->i_blink = NULL;
  137.    ip->i_name = nam;
  138.    ip->i_length = len;
  139.    return ip;
  140.    }
  141.  
  142. /*
  143.  * locinit -  clear local symbol table.
  144.  */
  145. novalue locinit()
  146.    {
  147.    dynoff = 0;
  148.    argoff = 0;
  149.    nlocal = -1;
  150.    nconst = -1;
  151.    static1 = lstatics;
  152.    }
  153.  
  154. /*
  155.  * putlocal - make a local symbol table entry.
  156.  */
  157. novalue putlocal(n, id, flags, imperror, procname)
  158. int n;
  159. char *id;
  160. register int flags;
  161. int imperror;
  162. char *procname;
  163.    {
  164.    register struct lentry *lp;
  165.    union {
  166.       struct gentry *gp;
  167.       int bn;
  168.       } p;
  169.  
  170.    if (n >= lsize)
  171.       quit("out of local symbol table space");
  172.    if (n > nlocal)
  173.       nlocal = n;
  174.    lp = &lltable[n];
  175.    lp->l_name = id;
  176.    lp->l_flag = flags;
  177.    if (flags == 0) {                /* undeclared */
  178.       if ((p.gp = glocate(id)) != NULL) {    /* check global */
  179.          lp->l_flag = F_Global;
  180.          lp->l_val.global = p.gp;
  181.          }
  182.  
  183.       else if ((p.bn = blocate(id)) != 0) {    /* check for function */
  184.          lp->l_flag = F_Builtin;
  185.          lp->l_val.global = putglobal(id, F_Builtin | F_Proc, -1, p.bn);
  186.          }
  187.  
  188.       else {                    /* implicit local */
  189.          if (imperror)
  190.             lwarn(id, "undeclared identifier, procedure ", procname);
  191.          lp->l_flag = F_Dynamic;
  192.          lp->l_val.offset = ++dynoff;
  193.          }
  194.       }
  195.    else if (flags & F_Global) {            /* global variable */
  196.       if ((p.gp = glocate(id)) == NULL)
  197.          quit("putlocal: global not in global table");
  198.       lp->l_val.global = p.gp;
  199.       }
  200.    else if (flags & F_Argument)            /* procedure argument */
  201.       lp->l_val.offset = ++argoff;
  202.    else if (flags & F_Dynamic)            /* local dynamic */
  203.       lp->l_val.offset = ++dynoff;
  204.    else if (flags & F_Static)            /* local static */
  205.       lp->l_val.staticid = ++lstatics;
  206.    else
  207.       quit("putlocal: unknown flags");
  208.    }
  209.  
  210. /*
  211.  * putglobal - make a global symbol table entry.
  212.  */
  213. struct gentry *putglobal(id, flags, nargs, procid)
  214. char *id;
  215. int flags;
  216. int nargs;
  217. int procid;
  218.    {
  219.    register struct gentry *p;
  220.  
  221.    if ((p = glocate(id)) == NULL) {    /* add to head of hash chain */
  222.       p = lghash[ghasher(id)];
  223.       lghash[ghasher(id)] = alcglobal(p, id, flags, nargs, procid);
  224.       return lghash[ghasher(id)];
  225.       }
  226.    p->g_flag |= flags;
  227.    p->g_nargs = nargs;
  228.    p->g_procid = procid;
  229.    return p;
  230.    }
  231.  
  232. /*
  233.  * putconst - make a constant symbol table entry.
  234.  */
  235. novalue putconst(n, flags, len, pc, valp)
  236. int n;
  237. int flags, len;
  238. word pc;
  239. union xval *valp;
  240.  
  241.    {
  242.    register struct centry *p;
  243.    if (n >= csize)
  244.       quit("out of constant table space");
  245.    if (nconst < n)
  246.       nconst = n;
  247.    p = &lctable[n];
  248.    p->c_flag = flags;
  249.    p->c_pc = pc;
  250.    if (flags & F_IntLit) {
  251.       p->c_val.ival = valp->ival;
  252.       }
  253.    else if (flags & F_StrLit) {
  254.       p->c_val.sval = valp->sval;
  255.       p->c_length = len;
  256.       }
  257.    else if (flags & F_CsetLit) {
  258.       p->c_val.sval = valp->sval;
  259.       p->c_length = len;
  260.       }
  261.    else    if (flags & F_RealLit)
  262.  
  263. #ifdef Double
  264. /* access real values one word at a time */
  265.     {  int *rp, *rq;    
  266.        rp = (int *) &(p->c_val.rval);
  267.        rq = (int *) &(valp->rval);
  268.        *rp++ = *rq++;
  269.        *rp   = *rq;
  270.     }
  271. #else                    /* Double */
  272.       p->c_val.rval = valp->rval;
  273. #endif                    /* Double */
  274.  
  275.    else
  276.       fprintf(stderr, "putconst: bad flags: %06o %011lo\n", flags, valp->ival);
  277.    }
  278.  
  279. /*
  280.  * putfield - make a record/field table entry.
  281.  */
  282. novalue putfield(fname, rnum, fnum)
  283. char *fname;
  284. int rnum, fnum;
  285.    {
  286.    register struct fentry *fp;
  287.    register struct rentry *rp, *rp2;
  288.    word hash;
  289.  
  290.    fp = flocate(fname);
  291.    if (fp == NULL) {        /* create a field entry */
  292.       nfields++;
  293.       hash = fhasher(fname);
  294.       fp = lfhash[hash];
  295.       lfhash[hash] = alcfhead(fp, fname, nfields, alcfrec((struct rentry *)NULL,
  296.          rnum, fnum));
  297.       return;
  298.       }
  299.    rp = fp->f_rlist;        /* found field entry, look for */
  300.    if (rp->r_recid > rnum) {    /*   spot in record list */
  301.       fp->f_rlist = alcfrec(rp, rnum, fnum);
  302.       return;
  303.       }
  304.    while (rp->r_recid < rnum) {    /* keep record list ascending */
  305.       if (rp->r_link == NULL) {
  306.          rp->r_link = alcfrec((struct rentry *)NULL, rnum, fnum);
  307.          return;
  308.          }
  309.       rp2 = rp;
  310.       rp = rp->r_link;
  311.       }
  312.    rp2->r_link = alcfrec(rp, rnum, fnum);
  313.    }
  314.  
  315. /*
  316.  * glocate - lookup identifier in global symbol table, return NULL
  317.  *  if not present.
  318.  */
  319. struct gentry *glocate(id)
  320. char *id;
  321.    {
  322.    register struct gentry *p;
  323.  
  324.    p = lghash[ghasher(id)];
  325.    while (p != NULL && p->g_name != id)
  326.       p = p->g_blink;
  327.    return p;
  328.    }
  329.  
  330. /*
  331.  * flocate - lookup identifier in field table.
  332.  */
  333. struct fentry *flocate(id)
  334. char *id;
  335.    {
  336.    register struct fentry *p;
  337.  
  338.    p = lfhash[fhasher(id)];
  339.    while (p != NULL && p->f_name != id)
  340.       p = p->f_blink;
  341.    return p;
  342.    }
  343.  
  344. /*
  345.  * alcglobal - create a new global symbol table entry.
  346.  */
  347. static struct gentry *alcglobal(blink, name, flag, nargs, procid)
  348. struct gentry *blink;
  349. char *name;
  350. int flag;
  351. int nargs;
  352. int procid;
  353.    {
  354.    register struct gentry *gp;
  355.  
  356.    if (lgfree >= &lgtable[gsize])
  357.       quit("out of global symbol table space");
  358.    gp = lgfree++;
  359.    gp->g_blink = blink;
  360.    gp->g_name = name;
  361.    gp->g_flag = flag;
  362.    gp->g_nargs = nargs;
  363.    gp->g_procid = procid;
  364.    return gp;
  365.    }
  366.  
  367. /*
  368.  * alcfhead - allocate a field table header.
  369.  */
  370. static struct fentry *alcfhead(blink, name, fid, rlist)
  371. struct fentry *blink;
  372. char *name;
  373. int fid;
  374. struct rentry *rlist;
  375.    {
  376.    register struct fentry *fp;
  377.  
  378.    if (lffree >= &lftable[fsize])
  379.       quit("out of field table space");
  380.    fp = lffree++;
  381.    fp->f_blink = blink;
  382.    fp->f_name = name;
  383.    fp->f_fid = fid;
  384.    fp->f_rlist = rlist;
  385.    return fp;
  386.    }
  387.  
  388. /*
  389.  * alcfrec - allocate a field table record list element.
  390.  */
  391. static struct rentry *alcfrec(link, rnum, fnum)
  392. struct rentry *link;
  393. int rnum, fnum;
  394.    {
  395.    register struct rentry *rp;
  396.  
  397.    if (lrfree >= &lrtable[rsize])
  398.       quit("out of field table space for record lists");
  399.    rp = lrfree++;
  400.    rp->r_link = link;
  401.    rp->r_recid = rnum;
  402.    rp->r_fnum = fnum;
  403.    return rp;
  404.    }
  405.  
  406. /*
  407.  * blocate - search for a function. The search is linear to make
  408.  *  it easier to add/delete functions. If found, returns index+1 for entry.
  409.  */
  410.  
  411. int blocate(s)
  412. register char *s;
  413.    {
  414.    register int i;
  415.    extern char *ftable[];
  416.    extern int ftbsize;
  417.  
  418.    for (i = 0; i < ftbsize; i++)
  419.       if (strcmp(ftable[i], s) == 0)
  420.      return i + 1;
  421.    return 0;
  422.    }
  423.